/** Easy parallelize job scheme.
 *
 *  Easy parallelize job scheme.
 *
 *  There are many group in this job, each group is form by some remote process
 *  and each in one group run in the same throw path.
 *
 *  @author : huicong
 *  @date : 2008-11-03
 *
 */

#ifndef _EASY_PARALLEL_JOB
#define _EASY_PARALLEL_JOB

#include "FrameJob.h"
#include "EasyParallelGroupManager.h"
#include "EasyParallelProcessManager.h"
#include "EasyParallelTask.h"


namespace bcmi_frame
{

    class EasyParallelJob : public FrameJob
    {
       
    public:

        EasyParallelJob();

        ~EasyParallelJob();

    public:

        HRESULT execute();

        VOID linkFrame(_IN ParallelFrame *_frame);

    public:
        /** Task Describe */

        /** Insert the _pid process into _gid group
         *
         *  NOTE : if the _pid or _gid not exits, or _pid is already in one group, do nothing and WORNING;
         *
         *  @param [IN] UINT _pid : id of process
         *  @param [IN] UINT _gid : id of group
         *
         */
        VOID insertGroup(IN UINT _pid, IN UINT _gid);

        /** Create a new process group
         * 
         *  @return : the number of all group N, the group id is N-1
         * 
         */
        UINT newGroup();

    private:

        /** master node doing */
        HRESULT masterNodeExecute();

        /** none master node doing */
        HRESULT restNodeExecute();

        HRESULT executeTask(INOUT FrameTask* _task);

        HRESULT initializeTask(INOUT FrameTask* _task);

        HRESULT finalizeTask(INOUT FrameTask* _task);

    private:
        /** Rest node call */

        /** 
         *  Generate task request from _task and then send to master node
         *
         *  |0123|4567|89012......|
         *
         *  0-3: current task id
         *  4-7: next task id
         *  8- : length = process number; v[i] = 1 means I need to send buffer to nodes[i-8]
         *
         *  @param [IN] FrameTask* _task : current task which has called execute()
         *  @return HRESULT : running status
         *
         */
        HRESULT genAndSendTaskRequest(IN FrameTask* _task);

        /** 
         *  Receive task response from master node and then let _task be the next task.
         *
         *  |0123|4567|89012......|
         *
         *  0-3: current task id
         *  4-7: next task id
         *  8- : length = process number; v[i] = 1 means I need to receive buffer to nodes[i-8]
         *
         *  @param [OUT] FrameTask* _task : find the task which has next task id
         *  @return HRESULT : running status
         *
         */
        HRESULT receiveAndGotoNextTask(OUT FrameTask* *_task);

    private:
        /** Master node call */

        /** Master handler function
         *
         *  Recv all buffer send to master node, do user function and then send response to rest node.
         *
         *  @param [IN] UINT _gid : group id
         *  @return HRESULT : running status
         *
         */
        HRESULT handleAndResponseGroup(IN UINT _gid);


    private:
        /** Master node use */

        EasyParallelProcessManager *_processManager;

    private:
        EasyParallelGroupManager *_groupManager;
        UINT _requestBufferSize;


    };

}; //namespace bcmi_frame

#endif //#ifndef _EASY_PARALLEL_JOB
